package org.neptune.web.controller;

import java.io.IOException;
import java.util.Map;

import javax.websocket.*;

import org.neptune.api.entity.Message;
import org.neptune.service.config.SpringApplicationContext;
import org.neptune.service.rabbit.CommentProducer;
import org.neptune.service.util.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;

/**
 * @author lwl
 * @date 2019/11/22 15:46
 */
// @ServerEndpoint(value = "/chattingRoom", configurator =
// WebSocketConfig.class)
// @Component
public class ChattingRoomServer {

	private static final Logger logger = LoggerFactory.getLogger(ChattingRoomServer.class);

	/**
	 * 全部在线会话 PS: 基于场景考虑 这里使用线程安全的Map存储会话对象。
	 */
	// 放入redis缓存更好
	private static Map<String, Session> onlineSessions = Maps.newConcurrentMap();

	/**
	 * 当客户端打开连接：1.添加会话对象 2.更新在线人数
	 */
	@OnOpen
	public void onOpen(Session session) {
		onlineSessions.put(session.getId(), session);
		sendMessageToAll(Message.jsonStr(Message.ENTER, "", "", onlineSessions.size()));
	}

	/**
	 * 当客户端发送消息：1.获取它的用户名和消息 2.发送消息给所有人
	 * <p>
	 * PS: 这里约定传递的消息为JSON字符串 方便传递更多参数！
	 */
	@OnMessage
	public void onMessage(Session session, String jsonStr) {
		Message message = JSON.parseObject(jsonStr, Message.class);
		sendMessageToAll(Message.jsonStr(Message.SPEAK,
				WebUtil.getNickName(WebUtil.getWebsocketUser(session)), message.getMsg(),
				onlineSessions.size()));
		CommentProducer commentProducer = SpringApplicationContext
				.getBeanByClass(CommentProducer.class);
		commentProducer.sender(session, message.getMsg());
	}

	/**
	 * 当关闭连接：1.移除会话对象 2.更新在线人数
	 */
	@OnClose
	public void onClose(Session session) {
		onlineSessions.remove(session.getId());
		sendMessageToAll(Message.jsonStr(Message.QUIT, "", "", onlineSessions.size()));
	}

	/**
	 * 当通信发生异常：打印错误日志
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		logger.error(WebUtil.getNickName(WebUtil.getWebsocketUser(session)) + " session error : ",
				error);
	}

	/**
	 * 公共方法：发送信息给所有人
	 */
	private void sendMessageToAll(String msg) {
		onlineSessions.forEach((id, session) -> {
			try{
				session.getBasicRemote().sendText(msg);
			} catch (IOException e){
				logger.error("socket send msg error : ", e);
			}
		});
	}
}
